package kotlincode

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*


fun main() {
//    flowTest01()
//    flowTest02()
    flowTest03()
}

private fun flowTest03() = runBlocking {
    launch {
        flow {
            emit(1)
            emit(2)
            emit(3)
        }
            .onCompletion {
                println("onCompletion first: this : $this")
                println("onCompletion first: it : $it")
            }
            .collect {
                println("collect: $it")
                if (it == 2) {
                    cancel()            // 1
                    println("cancel")
                }
            }
    }

    delay(100L)

    flowOf(4, 5, 6)
        .onCompletion { println("onCompletion second: $it") }
        .collect {
            println("collect: $it")
            // 仅用于测试，生产环境不应该这么创建异常
            throw IllegalStateException() // 2
        }
}

private fun flowTest02() = runBlocking {
    flow {
        println("emit 1")
        emit(1)
        println("emit 2")
        emit(2)
        println("emit 3")
        emit(3)
        println("emit 4")
        emit(4)
        println("emit 5")
        emit(5)
        println("emit 6")
        emit(6)
        println("emit 7")
        emit(7)
    }
        .onStart {
            println("onStart")
        }
        .onCompletion {
            println("onCompletion")
        }
        .filter {
            println("filter $it")
            it > 2
        }
        .map {
            println("map $it")
            it * it
        }
        .take(3)
        .collect {
            println("collect $it")
        }
}

private fun flowTest01() = runBlocking {
    flow {
        println("emit 1")
        emit(1)
        println("emit 2")
        emit(2)
        println("emit 3")
        emit(3)
        println("emit 4")
        emit(4)
        println("emit 5")
        emit(5)
        println("emit 6")
        emit(6)
        println("emit 7")
        emit(7)
    }.filter {
        println("filter $it")
        it > 2
    }
        .map {
            println("map $it")
            it * it
        }
        .take(3)
        .collect {
            println("collect $it")
        }

    listOf(1, 2, 3, 4, 5).filter { it > 2 }
        .map { it * 2 }
        .take(2)
        .forEach {
            println(it)
        }
}